﻿using System.Windows;
using System.Windows.Media;

namespace Com.Lancetinc.Evs.Reports.RadPdf;

internal static class MathHelper
{
    internal static Matrix Multiply(Matrix m1, Matrix m2)
    {
        return new Matrix(
            m1.M11 * m2.M11 + m1.M12 * m2.M21, m1.M11 * m2.M12 + m1.M12 * m2.M22,
            m1.M21 * m2.M11 + m1.M22 * m2.M21, m1.M21 * m2.M12 + m1.M22 * m2.M22,
            m1.OffsetX * m2.M11 + m1.OffsetY * m2.M21 + m2.OffsetX,
            m1.OffsetX * m2.M12 + m1.OffsetY * m2.M22 + m2.OffsetY);
    }

    internal static Matrix CreateMatrix(GeneralTransform transform)
    {
        if (transform != null && !IsIdentity(transform))
        {
            var offset = transform.Transform(new Point(0, 0));
            var i = transform.Transform(new Point(1, 0)).Minus(offset);
            var j = transform.Transform(new Point(0, 1)).Minus(offset);
            var matrix = new Matrix(i.X, i.Y, j.X, j.Y, offset.X, offset.Y);
            return matrix;
        }

        return Matrix.Identity;
    }

    internal static GeneralTransform GetGeneralTransform(FrameworkElement element, bool isRoot)
    {
        GeneralTransform transform = null;

        var parent = VisualTreeHelper.GetParent(element) as Visual;
        if (!isRoot && parent != null)
        {
            transform = element.TransformToVisual(parent);
        }
        else
        {
            var transformGroup = new TransformGroup();
            if (element.LayoutTransform != null)
            {
                transformGroup.Children.Add(element.LayoutTransform);
            }

            if (element.RenderTransform != null)
            {
                transformGroup.Children.Add(element.RenderTransform);
            }

            transform = transformGroup;
        }

        return transform;
    }

    internal static bool IsIdentity(GeneralTransform transform)
    {
        if (transform is MatrixTransform matrixTransform)
        {
            return matrixTransform.Matrix.IsIdentity;
        }

        if (transform is TranslateTransform translateTransform)
        {
            return translateTransform.X == 0 && translateTransform.Y == 0;
        }

        if (transform is RotateTransform rotateTransform)
        {
            return rotateTransform.Angle == 0;
        }

        return false;
    }

    internal static PathGeometry TransformRectangle(Matrix matrix, Rect rectangle)
    {
        var topLeft = matrix.Transform(new Point(rectangle.Left, rectangle.Top));
        var topRight = matrix.Transform(new Point(rectangle.Right, rectangle.Top));
        var bottomRight = matrix.Transform(new Point(rectangle.Right, rectangle.Bottom));
        var bottomLeft = matrix.Transform(new Point(rectangle.Left, rectangle.Bottom));

        var path = new PathGeometry();
        var figure = new PathFigure();
        path.Figures.Add(figure);
        figure.IsClosed = true;

        figure.StartPoint = topLeft;
        figure.Segments.Add(new LineSegment(topRight, false));
        figure.Segments.Add(new LineSegment(bottomRight, false));
        figure.Segments.Add(new LineSegment(bottomLeft, false));

        return path;
    }

    private static Point Minus(this Point first, Point second)
    {
        return new Point(first.X - second.X, first.Y - second.Y);
    }
}